Flutter PlatformViewLayer
PlatformViewLayer 是 Flutter Layer 的一种,用于 Hybrid composition 模式下的 UI 展示。
该类在 Flutter 中有两套实现:
- 一套位于 Flutter Framework,由 Dart 实现
- 一套位于 Flutter Engine,由 C++ 实现
Dart 实现
RenderObject 的 Layer 要通过 SceneBuilder 添加到 Scene 上,对应实现:
@override
void addToScene(ui.SceneBuilder builder) {
builder.addPlatformView(
viewId,
offset: rect.topLeft,
width: rect.width,
height: rect.height,
);
}
Flutter SceneBuilder 是从 Flutter Engine C++ 侧映射到 Dart 的类,这个调用将会调用 Flutter SceneBuilder 内的 C++ 方法。
而在 SceneBuilder 的 C++ 方法中,会创建一个 C++ 的 PlatformViewLayer 类,添加到 C++ 层的 LayerTree 中。这个 C++ 层的 LayerTree,将会传给 GPU 线程进行光栅化。
C++ 实现
类声明如下,通过对比可以清晰看出,类属性与 Dart 侧一致。核心在与 Preroll 和 paint 两个方法:
class PlatformViewLayer : public Layer {
public:
PlatformViewLayer(const SkPoint& offset, const SkSize& size, int64_t view_id);
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
void Paint(PaintContext& context) const override;
private:
SkPoint offset_;
SkSize size_;
int64_t view_id_;
FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewLayer);
};
Preroll
代码实现如下:
void PlatformViewLayer::Preroll(PrerollContext* context,
const SkMatrix& matrix) {
// 设置了平台视图的绘制边界
set_paint_boundsMakeXYWH(offset_.x(), offset_.y(), size_.width(,
size_.height()));
if (context->view_embedder == nullptr) {
FML_LOG(ERROR) << "Trying to embed a platform view but the PrerollContext "
"does not support embedding";
return;
}
// 表示这个上下文包含一个平台视图。
context->has_platform_view = true;
// 表示这个层的子树包含一个平台视图。
set_subtree_has_platform_view(true);
std::unique_ptr<EmbeddedViewParams> params =
std::make_unique<EmbeddedViewParams>(matrix, size_,
context->mutators_stack);
context->view_embedder->PrerollCompositeEmbeddedView(view_id_,
std::move(params));
}
其中,在 Android 下,PrerollCompositeEmbeddedView 将调用 AndroidExternalViewEmbedder 的 PrerollCompositeEmbeddedView 方法,在该方法内,实现了在 C++ 底层,对 PlatformView 的在真正渲染前的底层准备工作。
Paint
Paint 是 Hybrid composition 模式下,Flutter 侧 PlatformViewLayer 最底层的绘制方法。从 SkCanvas 中取出 AndroidExternalViewEmbedder 执行 CompositeEmbeddedView。
void PlatformViewLayer::Paint(PaintContext& context) const {
if (context.view_embedder == nullptr) {
FML_LOG(ERROR) << "Trying to embed a platform view but the PaintContext "
"does not support embedding";
return;
}
SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_);
context.leaf_nodes_canvas = canvas;
}
在 AndroidExternalViewEmbedder 的 CompositeEmbeddedView 方法中,
// |ExternalViewEmbedder|
SkCanvas* AndroidExternalViewEmbedder::CompositeEmbeddedView(int view_id) {
if (picture_recorders_.count(view_id) == 1) {
return picture_recorders_.at(view_id)->getRecordingCanvas();
}
return nullptr;
}
网络资源
- Flutter Hybrid Composition混合图层的原理分析 - 简书
- 在 Flutter 1.20, 官方推出了Hybrid Composition,此方法仿照ios端的platform view 在flutter中的显示方式,相较于原来的AndroidView性能要更好。
本文作者:Maeiee
本文链接:Flutter PlatformViewLayer
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!